Skip to content

feat(scripts): add policy release status and dispatch tooling - #261

Merged
Krishanx92 merged 3 commits into
wso2:mainfrom
renuka-fernando:release-scripts
Jul 30, 2026
Merged

feat(scripts): add policy release status and dispatch tooling#261
Krishanx92 merged 3 commits into
wso2:mainfrom
renuka-fernando:release-scripts

Conversation

@renuka-fernando

Copy link
Copy Markdown
Contributor

Purpose

Releasing policies today means manually checking, per policy, whether there are unreleased commits since the last git tag, whether the policy-definition.yaml version is bumped, and — for policies that depend on each other via go.mod — in what order to release them. This PR adds tooling to automate that analysis and to drive releases through the existing Release Policy workflow in dependency order.

Approach

  • Add scripts/policy-release/policy_release_status.py: fetches tags from upstream, inspects every policy, and writes a git-ignored policy-release-status.csv (uploadable to Google Sheets for further analysis).
    • Reports latest released version, yaml version, whether a release is needed, the reason (own changes vs dependency update), and whether it is ready to tag.
    • Derives inter-policy dependencies from go.mod, computes topological release waves, reverse dependents, and flags stale dependency pins.
    • Detects policy type (go vs python); dependency analysis applies only to go policies, and python policies additionally validate that pyproject.toml matches the yaml version.
    • Versions are stored without the v prefix so they feed straight into the release workflow.
  • Add scripts/policy-release/release_policies.py: reads the CSV and dispatches the Release Policy workflow via gh, wave by wave.
    • Dispatches all policies in a wave concurrently (async) and, by default, watches each run and reports pass/fail, with a barrier between waves.
    • Dispatch-only by design: it never edits go.mod or commits. Dry-run is the default; --execute performs the dispatch.
    • Holds back any release-ready policy with a stale dependency pin, so dependents are not released against an outdated embedded dependency.
  • Add scripts/policy-release/README.md documenting both scripts, all CSV columns, flags, and the dependency/safety model.
  • Git-ignore the generated CSV and Python caches.

Related Issues

N/A

Checklist

  • Tests added or updated (unit, integration, etc.)
  • Samples updated (if applicable)

Remarks

The scripts have been validated end-to-end against the current repository state: the status script produces the CSV (55 policies: 52 go, 3 python), and the release script dry-run correctly plans wave 0 releases and holds back mcp-auth due to a stale jwt-auth pin. --execute dispatches against wso2/gateway-controllers by default and therefore requires workflow-dispatch permission on that repo.

Add two scripts under scripts/policy-release/ to manage policy releases:
- policy_release_status.py: fetches upstream tags and reports each
  policy's release status to a CSV, including inter-policy go.mod
  dependency waves, release reason, and stale-pin detection.
- release_policies.py: dispatches the Release Policy workflow via gh in
  dependency-wave order, async within a wave with status reporting, and
  holds back policies with stale dependency pins (dispatch-only).

Also git-ignore the generated CSV and Python caches.

Signed-off-by: Renuka Fernando <renukapiyumal@gmail.com>
Distinguish go and python policies in policy_release_status.py:
- add policy_type column (go/python/unknown) detected as the release
  workflow does
- scope go.mod dependency analysis to go policies; python policies have
  no inter-policy deps and land in wave 0
- add version_files_consistent column and gate python release_ready on
  pyproject.toml matching the yaml version, with an anomaly warning
- update README to document the new columns and python handling

Signed-off-by: Renuka Fernando <renukapiyumal@gmail.com>
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@renuka-fernando, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 21 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d98883c4-ef57-4b4c-afa7-b1f3de6eb140

📥 Commits

Reviewing files that changed from the base of the PR and between 80facb4 and a0ec00f.

📒 Files selected for processing (2)
  • scripts/policy-release/policy_release_status.py
  • scripts/policy-release/release_policies.py
📝 Walkthrough

Summary

  • Added policy release status analysis that tracks versions, changes, dependencies, release readiness, waves, and stale dependency pins.
  • Added release workflow dispatch tooling with dependency-aware ordering, concurrent wave execution, dry-run defaults, monitoring, and failure barriers.
  • Added Python and Go version/dependency validation.
  • Documented both tools and ignored generated reports and Python cache artifacts.

Walkthrough

Adds tooling that scans policy metadata, tags, commits, versions, and Go dependencies to generate a release-status CSV. It derives dependency release waves, readiness, stale pins, and propagated release requirements. A second script consumes the CSV to dry-run or dispatch GitHub Actions workflows by wave, monitor results, and stop before later waves when a release fails. Documentation and ignore rules describe and support the workflow.

Sequence Diagram(s)

sequenceDiagram
  participant PolicyReleaseStatus
  participant StatusCSV
  participant ReleasePolicies
  participant GitHubActions
  PolicyReleaseStatus->>StatusCSV: Generate policy release status
  ReleasePolicies->>StatusCSV: Read release-ready rows and waves
  ReleasePolicies->>GitHubActions: Dispatch workflows for each wave
  GitHubActions-->>ReleasePolicies: Provide run status
  ReleasePolicies->>GitHubActions: Watch dispatched runs
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers purpose and approach, but omits many required template sections such as goals, release note, tests, and security checks. Add the missing template sections, especially Goals, Release note, Documentation, Automation tests, Security checks, and Test environment.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately reflects the main change: adding policy release status and dispatch tooling.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
scripts/policy-release/release_policies.py (2)

200-212: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Concurrent gh run watch output may interleave.

watch() streams directly to the console (capture=False) from multiple threads at once; output from concurrent runs can interleave in the terminal. Cosmetic only — final per-policy status is still printed correctly afterward.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/policy-release/release_policies.py` around lines 200 - 212, Update
the concurrent watch flow around watch() and ThreadPoolExecutor so each run’s gh
output is captured or otherwise synchronized before being written to the
console, preventing interleaved output from multiple threads. Preserve the
existing results mapping and final per-policy status behavior.

108-115: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

watch() conflates infra errors with workflow failure.

Any non-zero exit from gh run watch (including transient network/auth issues) is reported as "failure", which halts subsequent waves the same as a genuine workflow failure. This matches the documented fail-safe intent, but distinguishing gh CLI errors from an actual failed run conclusion (e.g., via gh run view --json conclusion) would avoid unnecessarily blocking releases on transient tooling issues.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/policy-release/release_policies.py` around lines 108 - 115, Update
watch() so non-zero gh run watch exits are distinguished from genuine workflow
failures: query the completed run’s conclusion using gh run view --json
conclusion, and only return "failure" when the workflow conclusion indicates
failure. Preserve the existing (run_id, conclusion) return contract while
representing transient gh CLI or infrastructure errors separately so they do not
get treated as workflow failures.
scripts/policy-release/policy_release_status.py (1)

99-114: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider real parsers instead of hand-rolled regex extraction.

read_yaml_name_version and read_pyproject_version extract values via line-anchored regex rather than yaml.safe_load/tomllib. This works for the simple unquoted scalars in this repo today, but is fragile against quoted strings, inline comments, or non-top-level indentation — any of which would silently corrupt policy_name/yaml_version/pyproject_version and cascade into wrong release-readiness computations.

♻️ Sketch using standard parsers
import tomllib

def read_pyproject_version(policy_dir: Path):
    pyproject = policy_dir / "pyproject.toml"
    if not pyproject.exists():
        return None
    with open(pyproject, "rb") as f:
        data = tomllib.load(f)
    return data.get("project", {}).get("version")

Also applies to: 149-159

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/policy-release/policy_release_status.py` around lines 99 - 114,
Replace the hand-rolled regex parsing in read_yaml_name_version and
read_pyproject_version with real parsers: use the repository’s YAML parser with
safe loading for policy-definition.yaml and tomllib.load for pyproject.toml.
Read only the intended top-level YAML name/version and project.version TOML
fields, preserve the existing missing-file/absent-value behavior, and return
parsed values without corruption from quoting, comments, or indentation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/policy-release/policy_release_status.py`:
- Around line 52-56: Update run() to propagate subprocess command failures
instead of returning empty output: invoke subprocess.run with failure checking
enabled and preserve stderr in the resulting exception or otherwise surface it
to callers. Keep successful commands returning stripped stdout, while ensuring
downstream functions such as fetch_upstream_tags, get_all_policy_tags, and
commits_since_tag receive an error rather than interpreting failed commands as
empty data.

In `@scripts/policy-release/release_policies.py`:
- Around line 64-105: The dispatch function should use the run ID returned by
the gh workflow run command instead of polling latest_run_id and comparing it
with before. Update the command invocation/output parsing to capture GitHub
Actions’ created run ID, return that ID on success, and remove the latest-run
polling logic from dispatch while preserving failure handling.

---

Nitpick comments:
In `@scripts/policy-release/policy_release_status.py`:
- Around line 99-114: Replace the hand-rolled regex parsing in
read_yaml_name_version and read_pyproject_version with real parsers: use the
repository’s YAML parser with safe loading for policy-definition.yaml and
tomllib.load for pyproject.toml. Read only the intended top-level YAML
name/version and project.version TOML fields, preserve the existing
missing-file/absent-value behavior, and return parsed values without corruption
from quoting, comments, or indentation.

In `@scripts/policy-release/release_policies.py`:
- Around line 200-212: Update the concurrent watch flow around watch() and
ThreadPoolExecutor so each run’s gh output is captured or otherwise synchronized
before being written to the console, preventing interleaved output from multiple
threads. Preserve the existing results mapping and final per-policy status
behavior.
- Around line 108-115: Update watch() so non-zero gh run watch exits are
distinguished from genuine workflow failures: query the completed run’s
conclusion using gh run view --json conclusion, and only return "failure" when
the workflow conclusion indicates failure. Preserve the existing (run_id,
conclusion) return contract while representing transient gh CLI or
infrastructure errors separately so they do not get treated as workflow
failures.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 48774962-60b8-4ac0-a559-4d2110afca16

📥 Commits

Reviewing files that changed from the base of the PR and between 6c3275e and 80facb4.

📒 Files selected for processing (4)
  • .gitignore
  • scripts/policy-release/README.md
  • scripts/policy-release/policy_release_status.py
  • scripts/policy-release/release_policies.py

Comment thread scripts/policy-release/policy_release_status.py Outdated
Comment thread scripts/policy-release/release_policies.py
Address review findings in the policy release tooling:
- policy_release_status.py: run() now surfaces non-zero command exits
  instead of returning "" (silently misread as no tags/commits); git
  fetch is a hard failure to avoid reporting against stale local tags.
- release_policies.py: dispatch() parses the run URL returned by gh
  workflow run (gh >= 2.87.0) for exact run-id attribution, falling back
  to polling on older gh; watch() queries the authoritative conclusion
  so transient gh/network errors are not reported as workflow failures.

Signed-off-by: Renuka Fernando <renukapiyumal@gmail.com>
@Krishanx92
Krishanx92 merged commit be10b13 into wso2:main Jul 30, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants